package com.wb.spring.boot.autoconfigure;

import com.wb.spring.boot.autoconfigure.model.WbProperties;
import com.wb.spring.boot.autoconfigure.proxy.WbClientProxy;
import com.wb.spring.boot.autoconfigure.stereotype.WbClient;
import com.wb.spring.boot.autoconfigure.utils.InterfacePathScanningCandidateComponentProvider;
import javassist.CannotCompileException;
import javassist.NotFoundException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import static java.lang.Class.forName;

/**
 * @author wenbin.xu
 * @date 2022/8/31 11:03
 */
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    private String packagesScan;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        // 解析
        Set<BeanDefinition> defs = parseInterfaces();
        for (BeanDefinition def : defs) {
            try {
                Class<?> clazz = forName(def.getBeanClassName());
                // 生成代理类
                Class<?> proxyClass = WbClientProxy.buildProxy(clazz);
                // 代理类注册为RootBeanDefinition后放入Spring中
                RootBeanDefinition beanDefinition = new RootBeanDefinition();
                beanDefinition.setBeanClass(proxyClass);
                beanDefinitionRegistry.registerBeanDefinition(proxyClass.getSimpleName().toLowerCase(), beanDefinition);
            } catch (ClassNotFoundException | NotFoundException | CannotCompileException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 解析
     *
     * @return
     */
    private Set<BeanDefinition> parseInterfaces() {
        // 解析
        InterfacePathScanningCandidateComponentProvider scanner = new InterfacePathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(WbClient.class));
        return new HashSet<>(scanner.findCandidateComponents(packagesScan));
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }

    public MyBeanDefinitionRegistryPostProcessor(String packagesScan) {
        this.packagesScan = packagesScan;
    }
}
